/**
 * 
 */
package com.example.gfw;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

/**
 * @author gfw
 *
 */
public class GFWView extends SurfaceView implements Runnable, Callback {

	private static final int DBG_LOG_ON = 0;
		
	private static final int m_nFPSInv = 50; //1/fps
	private static final int DIRECTION_0 = 0;
	private static final int DIRECTION_90 = 1;
	private static final int DIRECTION_180 = 2;
	private static final int DIRECTION_270 = 3;
	
    float m_fPlayerX, m_fPlayerY; //left-top of player
	private int m_nPlayerDirection;
	private int m_nScreenW, m_nScreenH;
	private float m_fSpeed = 3;
	private float m_fSpeedXSign = 1, m_fSpeedYSign = 1; 
	private Object m_LockTouch;
	private Canvas canvas = null;
	

	private Bitmap m_BMPPlayerArray[];
	
	private Bitmap m_BMPKeyArray[];
	private Rect m_rcKeyArray[];
	
	private SurfaceHolder m_SurfaceHolder;

	boolean m_bRunning = false;
	
	
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		
		if(keyCode == KeyEvent.KEYCODE_BACK)
			m_bRunning = false;
		
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		
		
		synchronized(m_LockTouch)
		{//saving cpu time on touch event
			try
			{
				m_LockTouch.wait(50);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
		
		if(m_bRunning )
		{
		
			if(event.getAction() == MotionEvent.ACTION_DOWN)
			{
				try
				{
					
					int x = (int)(event.getX());
					int y = (int)(event.getY());
			
					int index;
					for(index = 0; index < 4; index++)
					{
						if(PtInRect(x,y, m_rcKeyArray[index]) == 1)
							break;
					}
					
					if(index < 4)
					{
						m_nPlayerDirection = index;
						switch(index)
						{
						case DIRECTION_0:
							m_fSpeedXSign = 1;
							m_fSpeedYSign = 0;
							break;
						case DIRECTION_90:
                            m_fSpeedXSign = 0;
							m_fSpeedYSign = -1;
							break;
						case DIRECTION_180:
						    m_fSpeedXSign = -1;
							m_fSpeedYSign = 0;
							break;
						case DIRECTION_270:
                            m_fSpeedXSign = 0;
							m_fSpeedYSign = 1;
							break;
						}
					}
					
					if(DBG_LOG_ON != 0)
					{
                        String zsLog;
                        zsLog = String.valueOf(x) +","+ String.valueOf(y) + "," + String.valueOf(index);
                        Log.d("GFW TouchEvent", zsLog);
					}
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
			}
	
		}
		
		
		return super.onTouchEvent(event); //return true means event is handled so the parent will ignore the event
		
	}


	
	/**
	 * @param context
	 */
	public GFWView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		
		m_LockTouch = new byte[1]; //create an object to used a lock
		
		m_SurfaceHolder = this.getHolder();
		m_SurfaceHolder.addCallback(this);
		
		
		
		m_BMPPlayerArray = new Bitmap[4];
	  	m_BMPPlayerArray[DIRECTION_0] = BitmapFactory.decodeResource(this.getResources(), R.drawable.car0);
	  	m_BMPPlayerArray[DIRECTION_90] = BitmapFactory.decodeResource(this.getResources(), R.drawable.car90);
	  	m_BMPPlayerArray[DIRECTION_270] = BitmapFactory.decodeResource(this.getResources(), R.drawable.car270);
	  	m_BMPPlayerArray[DIRECTION_180] = BitmapFactory.decodeResource(this.getResources(), R.drawable.car180);
	  	
		
	  	m_BMPKeyArray = new Bitmap[4];
	  	m_BMPKeyArray[DIRECTION_0] = BitmapFactory.decodeResource(this.getResources(), R.drawable.key_right);
	  	m_BMPKeyArray[DIRECTION_90] = BitmapFactory.decodeResource(this.getResources(), R.drawable.key_up);
	  	m_BMPKeyArray[DIRECTION_180] = BitmapFactory.decodeResource(this.getResources(), R.drawable.key_left);
	  	m_BMPKeyArray[DIRECTION_270] = BitmapFactory.decodeResource(this.getResources(), R.drawable.key_down);
	  	
	  
	  	m_rcKeyArray = new Rect[4];
	    int index;
	    for(index = 0; index < 4; index++)
	    {
	    	m_rcKeyArray[index] = new Rect(0,0,0,0);
	    }
	  	
	  	
		this.setFocusable(true);
		
		if(DBG_LOG_ON != 0)
		{
			Log.d("GFW Init","OK");
		}
	}
	
	private int PtInRect(int x, int y, Rect rect)
	{
		if(x > rect.left && y > rect.top && x < rect.right && y < rect.bottom)
			return 1;
		
		return 0;
	}
	
	private void MyLogic()
	{
		
		try
		{
			int nPlayerW = m_BMPPlayerArray[m_nPlayerDirection].getWidth();
			int nPlayerH = m_BMPPlayerArray[m_nPlayerDirection].getHeight();
			
			m_fPlayerX += m_fSpeed * m_fSpeedXSign;
			m_fPlayerY += m_fSpeed * m_fSpeedYSign;
			
			
			if(m_fPlayerX < 0)
				m_fPlayerX = 0;
			if(m_fPlayerY < 0)
				m_fPlayerY = 0;
			
			if(m_fPlayerX + nPlayerW > m_nScreenW )
				m_fPlayerX = m_nScreenW - nPlayerW;
			if(m_fPlayerY + nPlayerH > m_nScreenH )
				m_fPlayerY = m_nScreenH - nPlayerH;
			
		
		}
		catch (Exception e)
		{

			e.printStackTrace();
		}
			
		if(DBG_LOG_ON != 0)
		{
			Log.d("GFW Logic","OK");
		}
		
	}
	
	private void MyDraw()
	{
		
		try
		{
			if(m_SurfaceHolder != null)
			{
				canvas = m_SurfaceHolder.lockCanvas();
				canvas.save();
			
				//a--clean 
				canvas.drawRGB(0, 0, 0);
				
				//b--draw player
				canvas.drawBitmap(m_BMPPlayerArray[m_nPlayerDirection], m_fPlayerX, m_fPlayerY,null);
				
				//c--draw key
				int index;
				for(index = 0; index < 4; index++)
				{
					canvas.drawBitmap(m_BMPKeyArray[index], m_rcKeyArray[index].left, m_rcKeyArray[index].top,null);
				}
				
				canvas.restore();
                                        
                                        
                if(DBG_LOG_ON != 0)
                {
                    Log.d("GFW Draw","OK");
                }
				
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		finally 
		{
			if(canvas != null)
			{
				m_SurfaceHolder.unlockCanvasAndPost(canvas);
			}
		}
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public GFWView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public GFWView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
	 */
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder)
	 */
	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		// TODO Auto-generated method stub

		{
			
		    if(DBG_LOG_ON != 0)
            {
                Log.d("GFW Create","enter");
            }
		    
			m_nScreenW = this.getWidth();
			m_nScreenH = this.getHeight();
		
			//1--init player status
			m_nPlayerDirection = DIRECTION_0;
			m_fPlayerX = this.getWidth()/2 - m_BMPPlayerArray[DIRECTION_0].getWidth()/2;
			m_fPlayerY = this.getHeight()/2 - m_BMPPlayerArray[DIRECTION_0].getHeight()/2;
	
			m_fSpeedXSign = 1;
			m_fSpeedYSign = 0;
                                        
            if(DBG_LOG_ON != 0)
            {
            	int nKeyWidth =m_rcKeyArray[DIRECTION_180].left ;
            	String zsLog = "player setup:" + String.valueOf(nKeyWidth);
                Log.d("GFW Init",zsLog);
            }
         
			
			//2--init key status
			int nKeyWidth = m_BMPKeyArray[DIRECTION_0].getWidth();
            int nKeyHeight = m_BMPKeyArray[DIRECTION_0].getHeight();
            m_rcKeyArray[DIRECTION_180].left = m_nScreenW - 3 * nKeyWidth;
            m_rcKeyArray[DIRECTION_180].top = m_nScreenH - 2 * nKeyHeight;
            m_rcKeyArray[DIRECTION_180].right = m_rcKeyArray[DIRECTION_180].left + nKeyWidth;
            m_rcKeyArray[DIRECTION_180].bottom = m_rcKeyArray[DIRECTION_180].top + nKeyHeight;
            
            m_rcKeyArray[DIRECTION_90].left = m_nScreenW - 2 * nKeyWidth;
            m_rcKeyArray[DIRECTION_90].top = m_nScreenH - 3 * nKeyHeight;
            m_rcKeyArray[DIRECTION_90].right = m_rcKeyArray[DIRECTION_90].left + nKeyWidth;
            m_rcKeyArray[DIRECTION_90].bottom = m_rcKeyArray[DIRECTION_90].top + nKeyHeight;
            
            m_rcKeyArray[DIRECTION_0].left = m_nScreenW -  1 * nKeyWidth;
            m_rcKeyArray[DIRECTION_0].top = m_nScreenH - 2 * nKeyHeight;
            m_rcKeyArray[DIRECTION_0].right = m_rcKeyArray[DIRECTION_0].left + nKeyWidth;
            m_rcKeyArray[DIRECTION_0].bottom = m_rcKeyArray[DIRECTION_0].top + nKeyHeight;
            
             
            m_rcKeyArray[DIRECTION_270].left = m_nScreenW -  2 * nKeyWidth;
            m_rcKeyArray[DIRECTION_270].top = m_nScreenH - 1 * nKeyHeight;
            m_rcKeyArray[DIRECTION_270].right = m_rcKeyArray[DIRECTION_270].left + nKeyWidth;
            m_rcKeyArray[DIRECTION_270].bottom = m_rcKeyArray[DIRECTION_270].top + nKeyHeight;
            
	        if(DBG_LOG_ON != 0)
            {
                Log.d("GFW Init","key setup");
            }
					
			new Thread(this).start();
			m_bRunning = true;
	
                                        
            if(DBG_LOG_ON != 0)
            {
                Log.d("GFW Create","OK");
            }
			
		
		}
		
	}

	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder)
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub

		m_bRunning = false;
	}

	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while(m_bRunning)
		{
			long nStartTime = System.currentTimeMillis();
			MyLogic();
			MyDraw();
		
			long nTimeSpan = System.currentTimeMillis() - nStartTime;
			if(nTimeSpan < m_nFPSInv)
			{
				long nWaitTime = m_nFPSInv - nTimeSpan;
                try
                {
                   Thread.sleep(nWaitTime);
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
			
			}
		}

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
